package common

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/golang-jwt/jwt/v5"
	"private-domain-overseas-service/pkg/xerr"
	"strconv"
	"time"
)

// JwtAdminCreate Generate jwt
func JwtAdminCreate(jwtSecret string, expire int64, mallUserId, roleIds, buttonIds string) (string, error) {
	t := time.Now().Unix()
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"rids": roleIds,
		"bids": buttonIds,
		"bsu":  mallUserId,
		"aud":  mallUserId,
		"nbf":  t,
		"iat":  t,
		"exp":  t + expire,
	})
	tokenString, err := token.SignedString([]byte(jwtSecret))
	if err != nil {
		return "", err
	}
	return tokenString, nil
}

// JwtAdminValidate 后台验证token并提取用户信息
func JwtAdminValidate(jwtSecret, tokenString string) (string, string, string, error) {
	// 定义方法检索私钥
	keyFunc := func(token *jwt.Token) (interface{}, error) {
		// Ensure the token's signing method is HMAC (HS256)
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("unexpected signing method")
		}
		return []byte(jwtSecret), nil
	}

	// 解析验证token，会验证是否过期
	token, err := jwt.Parse(tokenString, keyFunc)
	if err != nil {
		return "", "", "", err
	}

	// 提取claims
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		// 判断token是否过期
		if expiredAt, ok := claims["exp"].(float64); ok {
			if expiredAt < float64(time.Now().Unix()) {
				return "", "", "", xerr.ErrCodeMsg(xerr.ServerTokenExpireError, "无效token")
			}
		}
		// 提取用户信息
		mallUserId, userIdExists := claims["bsu"].(string)
		roleIds, roleIdExists := claims["rids"].(string)
		buttonIds, buttonIdExists := claims["bids"].(string)
		if userIdExists && roleIdExists && buttonIdExists {
			return mallUserId, roleIds, buttonIds, nil
		}
		return "", "", "", xerr.ErrCodeMsg(xerr.ServerTokenInvalidError, "无效token")
	}

	return "", "", "", xerr.ErrCodeMsg(xerr.ServerTokenInvalidError, "无效token")
}

// JwtAdminAuthUserId - 获取当前用户id
func JwtAdminAuthUserId(ctx context.Context) int64 {
	useId, err := strconv.ParseInt(ctx.Value("bsu").(string), 10, 32)
	if err != nil {
		return -1
	}
	return useId
}

// JwrAdminAuthRoleId - 获取用户相关角色id
func JwrAdminAuthRoleId(ctx context.Context) []int {
	var roleIds []int
	err := json.Unmarshal([]byte(ctx.Value("rids").(string)), &roleIds)
	if err != nil {
		return nil
	}
	return roleIds
}
